﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharedGenomics.Workbench.Core
{
    public abstract class ViewFactory<T> : IViewFactory
    {
        #region IViewFactory Members

        public IView CreateView(IPresenter presenter)
        {
            //get the view for the presenter and find all the regions on it
            T parentView = (T)presenter.View;

            IDictionary<string, T> viewRegions = this.GetRegionItems<T>(parentView);

            if (viewRegions.Count > 0)
            {
                //get all the properties on the presenter marked with [Region] attributes - these should all expose presenters
                IDictionary<string, IPresenter> regionedSubPresenters = this.GetRegionItems<IPresenter>(presenter);

                //get the views for each 'sub-presenter' on the input presenter which corresponds to a region on the parent view (i.e. the view associated with the 
                //input presenter)
                foreach (var kvp in regionedSubPresenters)
                {
                    string currentRegionName = kvp.Key;

                    if (viewRegions.ContainsKey(currentRegionName))
                    {
                        //register for help requested events on the current presenter's view
                        //kvp.Value.View.HelpRequired += new EventHandler<HelpRequiredEventArgs>(View_HelpRequired);

                        //get the (possibly nested) view for the presenter associated with the current view region
                        IView nestedView = this.CreateView(kvp.Value);
                        this.SetNestedView(nestedView, viewRegions[currentRegionName]);
                    }
                }
            }

            return (IView)parentView;
        }

        public abstract IViewDialog CreateDialog(IPresenter presenter);

        #endregion

        protected abstract void SetNestedView(IView nestedView, T parent);

        private IDictionary<string, TTarget> GetRegionItems<TTarget>(object parent)
        {
            Dictionary<string, TTarget> regions = new Dictionary<string, TTarget>();

            var regs = from p in parent.GetType().GetProperties()
                       let atts = p.GetCustomAttributes(typeof(RegionAttribute), false)
                       where atts.Length == 1
                       select new { RegionName = ((RegionAttribute)atts[0]).Name, Value = (TTarget)p.GetValue(parent, null) };

            foreach (var r in regs)
            {
                if (!regions.ContainsKey(r.RegionName))
                    regions[r.RegionName] = r.Value;
            }

            return regions;
        }
    }
}
